package com.upbos.upm.common.exception;

import com.alibaba.fastjson.JSON;
import com.upbos.core.ret.RetCode;
import com.upbos.core.ret.RetData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class GlobalExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception ex) {

        RetData retData = new RetData(RetCode.FAIL);

        if (ex instanceof BindException) {
            // 处理参数绑定异常
            BindException bex = (BindException) ex;
            List<FieldError> fieldErrors = bex.getBindingResult().getFieldErrors();
            retData = onBindError(fieldErrors);
        } else if (ex instanceof MethodArgumentNotValidException) {
            // 参数有注解@ResponseBody，处理参数校验异常
            MethodArgumentNotValidException mex = (MethodArgumentNotValidException) ex;
            List<FieldError> fieldErrors = mex.getBindingResult().getFieldErrors();
            retData = onBindError(fieldErrors);
        } else {
            retData.setMsg(RetCode.UNKNOWN_EXCEPTION.getMsg());
            retData.setData(ex.getMessage() == null ? "空指针异常" : ex.getMessage());
        }
        handleAjaxError(response, retData);
        log.error("全局异常处理中心：", ex);
        return new ModelAndView();
    }

    private RetData onBindError(List<FieldError> fieldErrors) {
        Map<String, Object> attrMap = new HashMap<String, Object>(16);
        for (FieldError error : fieldErrors) {
            attrMap.put(error.getField(), error.getDefaultMessage());
        }

        RetData resData = new RetData(RetCode.PARAMETER_FORMAT_ERROR);
        resData.setData(attrMap);
        return resData;
    }

    private void handleAjaxError(HttpServletResponse response, RetData retData) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        response.setStatus(500);
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.write(JSON.toJSONString(retData));
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
